package com.easipass.lgsa.portRelease.util;

import com.easipass.lgsa.portRelease.exception.BusinessTypeException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

public class Toos {

    private static final Log log = LogFactory.getLog(Toos.class);
    private static Gson gson = new GsonBuilder().serializeNulls().create();
    public static Integer CTCINIT = 0;
    //状态
    public static String TEMP = "1"; //暂存
    public static String COMMIT = "2"; //提交生效
    public static String ENTRY = "3"; //海关入库
    public static String ENTRYFAIL = "4"; //海关入库失败
    public static String AUDITPASS = "5"; //审核通过
    public static String AUDITREJECTION = "6"; //审核拒绝
    public static String TURNTOMAN = "17"; //转人工
    public static String DECLARED = "18"; //已申报
    public static String CANCELDECLARED = "95";//作废申报
    public static String CANCEL = "96"; //作废
    public static String DELETE = "99"; //删除
    public static String CUSTOMDELETE = "100"; //海关删除
    public static String INEXPADD = "101"; //出入库信息新增
    public static String SYNCHRONIZED = "102"; //出入库信息同步
    public static String INEXPDELETE = "103"; //出入库信息删除
    public static String ENTRUST = "104"; //已委托
    public static String UNENTRUST = "105"; //取消委托
    public static String GATEPASS = "51"; //已过卡
    public static String GATENOPASS = "50"; //未过卡
    public static String REFUSEPASS = "52"; //拒绝过卡
    public static String RELISTPASS = "53"; //卡口放行
    public static String GATEPASSING = "54"; //正在过卡
    public static String CHECKED = "55"; //正在查验

    //申报类型代码
    public static String DCLTYPECD1 = "1"; //备案
    public static String DCLTYPECD2 = "2"; //变更
    public static String DCLTYPECD3 = "3"; //作废

    public static String CUSTOM_AUDITPASS = "1";
    public static String CUSTOM_TURNTOMAN = "2";
    public static String CUSTOM_AUDITREJECTION = "3";
    public static String CUSTOM_ENTRY = "Y";
    public static String CUSTOM_ENTRYFAIL = "Z";

    //返回ReturnInfo 1 或 0
    public static String RIONE = "1";
    public static String RIZERO = "0";


    /**
     * 判断非负数的整数或者携带一位或者六位的小数
     */
    public static boolean isNumber(String str) {
        boolean flag = false;
        try {
            Pattern pattern = Pattern.compile("^[+]?([0-9]+(.[0-9]{1,6})?)$");
            if (pattern.matcher(str).matches()) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 判断是否是整数且小于等于2147483647
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */

    public static boolean isInteger(String str) {
        boolean flag = false;
        try {
            Pattern pattern = Pattern.compile("^[+]?[\\d]*$");
            if (pattern.matcher(str).matches()) {
                if (Long.parseLong(str) <= 2147483647) {
                    flag = true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    public static boolean isAllNumber(String str) {
        boolean flag = false;
        try {
            if (Pattern.compile("^[+]?[\\d]*$").matcher(str).matches()) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }


    /**
     * 判断是否是正整数且
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static boolean isIntegerWithoutZero(String str) {
        boolean flag = false;
        try {
            Pattern pattern = Pattern.compile("^[1-9][\\d]*$");
            if (pattern.matcher(str).matches()) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    // decimalNumber为小数点后允许的位数
    public static boolean isNumber(String str, String integerNumber, String decimalNumber) {
        boolean flag = false;
        try {
            if (str.length() > 20) {
                return flag;
            } else if (str.length() == 20 && !str.contains(".")) {
                return flag;
            } else {
                // Pattern pattern = Pattern.compile("^[+]?([0-9]{1," + integerNumber + "}+(.[0-9]{1," + decimalNumber + "})?)$");
                Pattern pattern = Pattern.compile("^[+]?\\d{1," + integerNumber + "}(\\.\\d{1," + decimalNumber + "})?$");
                if (pattern.matcher(str).matches()) {
                    flag = true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 判断是否是正整数且小于等于200
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static boolean isIntegerWithoutZeroAndLess(String str) {
        boolean flag = false;
        try {
            Pattern pattern = Pattern.compile("^[1-9][\\d]*$");
            if (pattern.matcher(str).matches()) {
                if (Long.parseLong(str) <= 200) {
                    flag = true;
                }
				/*if (Integer.parseInt(str)<= 200 ) {
					flag = true;
				}*/
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    public static Date stringToDate(String date) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date datedest = null;
        try {
            if (date.length() <= 11) {
                datedest = simpleFormat.parse(date);
            } else {
                datedest = format.parse(date);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return datedest;
    }

    public static String getStringDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return formatter.format(date.getTime());
    }


    public static void copyValueIfNull(Object dest, Object source) {
        Field[] fields = dest.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            String name = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            try {
                Method getDestMethod = dest.getClass().getMethod("get" + name);
                Object destValue = getDestMethod.invoke(dest);
                if (null == destValue || StringUtils.isBlank(destValue.toString())) {
                    Method getsourceMethod = source.getClass().getMethod("get" + name);
                    Object sourceValue = getsourceMethod.invoke(source);
                    if (sourceValue != null) {
                        if (String.class == field.getType()) {
                            if (Date.class == source.getClass().getDeclaredField(field.getName()).getType()) {
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                field.set(dest, sdf.format(sourceValue));
                            } else {
                                field.set(dest, sourceValue.toString());
                            }
                        } else if (Integer.class == field.getType()) {
                            if (String.class == source.getClass().getDeclaredField(field.getName()).getType()) {
                                field.set(dest, Integer.parseInt(sourceValue.toString()));
                            } else {
                                field.set(dest, sourceValue);
                            }
                        } else if (Date.class == field.getType()) {
                            if (String.class == source.getClass().getDeclaredField(field.getName()).getType()) {
                                if (sourceValue.toString().length() > 10) {
                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                    field.set(dest, sdf.parse(sourceValue.toString()));
                                } else {
                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                                    field.set(dest, sdf.parse(sourceValue.toString()));
                                }
                            } else {
                                field.set(dest, sourceValue);
                            }
                        } else if (BigDecimal.class == field.getType()) {
                            field.set(dest, new BigDecimal(sourceValue.toString()));
                        } else {
                            field.set(dest, sourceValue);
                        }
                    }
                }
            } catch (NoSuchMethodException ignored) {
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 判断list中是否有重复元素,没有相同元素为true
     *
     * @param list
     * @return
     */
    public static boolean hasSame(List<? extends Object> list) {
        if (null == list) {
            return false;
        }
        return list.size() == new HashSet<Object>(list).size();
    }


    public static Map<String, String> importMap() {
        Map<String, String> map = new HashMap<>();
        map.put("所在关区名称", "customName");
        map.put("申报单位", "dclUnitcd");
        map.put("关联单证表体", "sasPassportRtl");
        map.put("表体", "sasPassportDt");
        map.put("操作状态", "optStatus");
        map.put("商品料号", "gdsMtno");
        map.put("序号", "passportSeqno");
        map.put("审批标记代码", "emapvMarkcd");
        map.put("商品编码", "gdecd");
        map.put("车架重", "vehicleFrameWt");
        map.put("核放单编号", "passportNo");
        map.put("核放单预录入编号", "sasPassportPreentNo");
        map.put("创建时间", "createTime");
        map.put("进出标志", "ioTypecd");
        map.put("货物总净重", "totalNetWt");
        map.put("计量单位名称", "unitName");
        map.put("绑定类型", "bindTypecd");
        map.put("申报时间", "dclTime");
        map.put("关联单证类型", "rltTbTypecd");
        map.put("区内企业名称", "areainEtpsNm");
        map.put("区内企业编码", "areainEtpsno");
        map.put("总重量", "totalWt");
        map.put("卡口ID2", "secdPassId");
        map.put("区内企业社会信用代码", "areainEtpsSccd");
        map.put("PK", "id");
        map.put("类型", "passportTypecd");
        map.put("变更次数", "chgTmsCnt");
        map.put("货物毛重", "grossWt");
        map.put("组织id", "orgId");
        map.put("IC卡号(电子车牌)", "vehicleIcNo");
        map.put("操作时间", "optTime");
        map.put("申报类型代码", "dclTypecd");
        map.put("明细ID", "pid");
        map.put("备注", "rmk");
        map.put("卡口ID1", "passId");
        map.put("重量比对误差", "wtError");
        map.put("文件名", "fileName");
        map.put("过卡时间1", "passTime");
        map.put("主管关区代码", "masterCuscd");
        map.put("集装箱号", "containerNo");
        map.put("商品名称", "gdsNm");
        map.put("关联商品序号", "rltGdsSeqno");
        map.put("集装箱箱型", "containerType");
        map.put("车自重", "vehicleWt");
        map.put("备用4", "col4");
        map.put("备用2", "col2");
        map.put("备用3", "col3");
        map.put("备用1", "col1");
        map.put("关联单证编号", "rltNo");
        map.put("操作用户id", "optUserId");
        map.put("货物总毛重", "totalGrossWt");
        map.put("组织编号", "orgCode");
        map.put("状态代码", "stucd");
        map.put("车架号", "vehicleFrameNo");
        map.put("所属系统", "ownerSystem");
        map.put("到检状态", "logisticsStucd");
        map.put("集装箱重", "containerWt");
        map.put("货物净重", "netWt");
        map.put("卡口地磅采集重量", "passCollectWt");
        map.put("申请人及联系方式", "dclErConc");
        map.put("过卡时间2", "secdPassTime");
        map.put("承运车车牌号", "vehicleNo");
        map.put("申报数量", "dclQty");
        map.put("代理组织编号", "proxyOrgCode");
        map.put("供应商组织编号", "supplierOrgCode");
        return map;
    }

    public static Map<String, String> IN_EXP_TYPE_MAP = new HashMap<>();

    public static Map<String, String> IE_TYPECD_MAP = new HashMap<>();

    public static Map<String, String> BIND_TYPECD_MAP = new HashMap<>();

    public static Map<String, String> MTPCK_ENDPRT_TYPECD_MAP = new HashMap<>();

    public static Map<String, String> OPT_STATUS_MAP = new HashMap<>();

    public static Map<String, String> CHECK_RESULT_MAP = new HashMap<>();

    public static Map<String, String> IMPORT_MAP = new HashMap<>();

    static {
        IN_EXP_TYPE_MAP.put("1", "非径予放行货物");
        IN_EXP_TYPE_MAP.put("2", "先报后送");
        IN_EXP_TYPE_MAP.put("3", "分送集报");
        IN_EXP_TYPE_MAP.put("4", "区内流转");
        IN_EXP_TYPE_MAP.put("5", "区间流转");
        IN_EXP_TYPE_MAP.put("6", "进出境径予放行");
        IN_EXP_TYPE_MAP.put("0", "空车进出区");

        IE_TYPECD_MAP.put("I", "进区");
        IE_TYPECD_MAP.put("E", "出区");

        BIND_TYPECD_MAP.put("1", "一车多票");
        BIND_TYPECD_MAP.put("2", "一票一车");
        BIND_TYPECD_MAP.put("3", "一票多车");

        MTPCK_ENDPRT_TYPECD_MAP.put("I", "料件");
        MTPCK_ENDPRT_TYPECD_MAP.put("E", "成品");
        MTPCK_ENDPRT_TYPECD_MAP.put("S", "设备");

        OPT_STATUS_MAP.put("1", "暂存");
        OPT_STATUS_MAP.put("2", "提交生效");
        OPT_STATUS_MAP.put("3", "入库成功");
        OPT_STATUS_MAP.put("4", "入库失败");
        OPT_STATUS_MAP.put("5", "审核通过");
        OPT_STATUS_MAP.put("6", "审核拒绝");
        OPT_STATUS_MAP.put("17", "转人工");
        OPT_STATUS_MAP.put("24", "结案");
        OPT_STATUS_MAP.put("25", "结案申报");
        OPT_STATUS_MAP.put("18", "已申报");
        OPT_STATUS_MAP.put("96", "作废");
        OPT_STATUS_MAP.put("99", "删除");
        OPT_STATUS_MAP.put("51", "已过卡");
        OPT_STATUS_MAP.put("50", "未过卡");
        OPT_STATUS_MAP.put("52", "拒绝过卡");
        OPT_STATUS_MAP.put("53", "卡口放行");

        CHECK_RESULT_MAP.put("1", "补证");
        CHECK_RESULT_MAP.put("2", "补税");
        CHECK_RESULT_MAP.put("3", "补证补税");
        CHECK_RESULT_MAP.put("4", "罚没");
        CHECK_RESULT_MAP.put("5", "处罚");
        CHECK_RESULT_MAP.put("6", "退运");


        IMPORT_MAP.put("ERP/WMS出入库编号", "inExpWhNo");
        IMPORT_MAP.put("出入库类型", "inExpType");
        IMPORT_MAP.put("ERP/WMS出入库日期", "inExpTime");
        IMPORT_MAP.put("进出标志", "ieTypecd");
        IMPORT_MAP.put("料件成品标志", "mtpckEndprdTypecd");
        IMPORT_MAP.put("进出境关别", "impexpPortcd");
        IMPORT_MAP.put("境内收发货企业名称", "rcvgdEtpsNm");
        IMPORT_MAP.put("境内收发货企业编码", "rcvgdEtpsNo");
        IMPORT_MAP.put("境内收发货企业社会信用代码", "rcvgdEtpsSccd");
        IMPORT_MAP.put("承运车车牌号", "vehicleNo");
        IMPORT_MAP.put("集装箱号", "containerNo");
        IMPORT_MAP.put("车自重", "vehicleWt");
        IMPORT_MAP.put("车架号", "vehicleFrameNo");
        IMPORT_MAP.put("车架重", "vehicleFrameWt");
        IMPORT_MAP.put("集装箱箱型", "containerType");
        IMPORT_MAP.put("集装箱重", "containerWt");
        IMPORT_MAP.put("总重量", "totalWt");
        IMPORT_MAP.put("货物总毛重", "totalGrossWt");
        IMPORT_MAP.put("货物总净重", "totalNetWt");
        IMPORT_MAP.put("备注", "rmk");
        IMPORT_MAP.put("绑定类型", "bindTypecd");

        IMPORT_MAP.put("关联单证", "portReleaseRlt");
        IMPORT_MAP.put("关联单证类型", "rltTbTypecd");
        IMPORT_MAP.put("关联单证编号", "rltNo");

        IMPORT_MAP.put("表体", "portReleaseDt");
        IMPORT_MAP.put("关联明细序号", "rltSeqno");
        IMPORT_MAP.put("商品料号", "gdsMtno");
        IMPORT_MAP.put("商品编码", "gdecd");
        IMPORT_MAP.put("商品名称", "gdsNm");
        IMPORT_MAP.put("规格型号", "gdsSpcfModelDesc");
        IMPORT_MAP.put("币制", "dclCurrcd");
        IMPORT_MAP.put("申报数量", "dclQty");
        IMPORT_MAP.put("申报计量单位", "dclUnitcd");
        IMPORT_MAP.put("原产国（地区）", "natcd");
        IMPORT_MAP.put("净重", "netWt");

        IMPORT_MAP.put("出入库单", "portReleaseInexpRlt");
        IMPORT_MAP.put("出入库编号", "inExpWhNo");
        IMPORT_MAP.put("出入库日期", "inExpTime");

    }

    /**
     * 日期校验
     */
    public static boolean isLegalDate(String sDate) throws Exception {
        int legalLen = 19;
        if ((null == sDate) || (sDate.length() != legalLen)) {
            throw new BusinessTypeException("日期长度错误");
        }
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = formatter.parse(sDate);
            return sDate.equals(formatter.format(date));
        } catch (Exception e) {
            return false;
        }
    }


}
